package com.qf.hospital.controller;

import com.alibaba.druid.util.StringUtils;
import com.github.pagehelper.PageInfo;
import com.qf.hospital.DTO.ReportDTO;
import com.qf.hospital.VO.*;
import com.qf.hospital.entity.*;
import com.qf.hospital.enums.HospitalExceptionEnum;
import com.qf.hospital.service.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author 何星宇
 * @version V1.0
 * @Date 2021/10/20 10:54
 */

@RestController
public class CaoController {
    private Logger log = LoggerFactory.getLogger(CaoController.class);
    @Autowired
    private ReportService reportService;
    @Autowired
    private DepartmentService departmentService;
    @Autowired
    private RegisteredTypeService registeredTypeService;
    @Autowired
    private DoctorService doctorService;
    @Autowired
    private PharmacyService pharmacyService;
    @Autowired
    private CashierService cashierService;
    @Autowired
    private OutPatientTypeService outPatientTypeService;
    //用户挂号
    //================================折叠头部==================================
    /**
     * 根据条件查询挂号信息
     *
     * @param cc
     * @param name
     * @return
     */
    @GetMapping("/cao/index")
    public List<ReportVO> index(@RequestParam(defaultValue = "1") Integer cc, String name) {
        //调用service层获取数据
        List<ReportVO> data = reportService.findPatientInfo(cc, name);
        return data;
    }

    /**
     * 查询所有科室类型
     *
     * @return
     */
    @PostMapping("/cao/seldep")
    public List<DepartmentVO> seldep() {
        //调用service查询数据
        List<DepartmentVO> data = departmentService.findAll();
        return data;
    }

    /**
     * 查询所有挂号类型
     *
     * @return
     */
    @PostMapping("/cao/selreg")
    public List<RegisteredTypeVO> selreg() {
        List<RegisteredTypeVO> data = registeredTypeService.findAll();
        return data;
    }

    /**
     * 查询医生信息（根据科室&挂号类型）
     *
     * @param registeredId
     * @param departmentId
     * @return
     */
    @PostMapping("/cao/seldoctor")
    public List<DoctorVO> seldoctor(Integer registeredId, Integer departmentId) {
        //校验
        if (registeredId == null || departmentId == null) {
            //记录日志
            log.info("【根据条件查询医生信息】 科室或挂号类型为必填项");
            return null;
        }
        List<DoctorVO> data = doctorService.findDoctorByRegisterdIdAndDepartmentId(registeredId, departmentId);
        return data;
    }

    /**
     * 手机号&身份证号校验
     *
     * @param phone
     * @param carid
     * @return
     */
    @PostMapping("/cao/phone")
    public Integer checkPhoneAndCarid(String phone, String carid) {
        Integer result = reportService.checkPhoneAndCarid(phone, carid);
        return result;
    }

    /**
     * 查询挂号费用
     *
     * @param registeredId
     */
    @PostMapping("/cao/selRegMoney")
    public Double selRegMoney(Integer registeredId) {
        RegisteredType registeredType = registeredTypeService.findById(registeredId);
        Double price = registeredType.getPrice();
        return price;
    }

    /**
     * 添加患者信息
     * @param reportDTO
     * @return
     */
    @PostMapping("/cao/addReport")
    public R addReport(@Valid ReportDTO reportDTO, BindingResult bindingResult){
        //校验
        if (bindingResult.hasErrors()){
            String msg = bindingResult.getFieldError().getDefaultMessage();
            //记录日志
            log.info("【添加患者信息】 参数不合法，msg: {}",msg);
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,msg);
        }

        //获取当前系统登录用户
        Subject subject = SecurityUtils.getSubject();
        SysUser sysUser = (SysUser) subject.getPrincipal();
        if (sysUser==null){
            //记录日志
            log.info("【登录超时】 请重新登录");
            return R.error(HospitalExceptionEnum.LOGIN_TIMEOUT);
        }
        reportDTO.setUsers(sysUser.getRealName());
        //调用service添加数据
        reportService.addReport(reportDTO);
        return R.ok("添加患者信息成功");
    }

    /**
     * 删除患者信息
     * @param id report表主键id
     * @return
     */
    @PostMapping("/cao/delre")
    public R delre(Integer id){
        //校验
        if (id==null){
            //记录日志
            log.info("【删除患者信息】 id不可为空");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"id不可为空");
        }

        //调用service将患者信息的state字段修改为0
        reportService.deleteReportById(id);
        return R.ok("删除患者信息成功！");

    }

    /**
     * 查询患者是否有未缴费的药品
     * @param reportId 患者id
     * @return
     */
    @PostMapping("/caoout/selch")
    public Integer selch(Integer reportId){
        //校验
        if (reportId==null){
            //记录日志
            log.info("【查询患者是否有未缴费的药品】 患者id为必传项");
            return null;
        }
        //调用service查询患者的药品缴费状态
        Integer result = cashierService.findDrugPaymentStatusByReportId(reportId);
        return result;
    }

    /**
     * 查询患者是否有未缴费的项目
     * @param reid 患者id
     * @return
     */
    @PostMapping("/caocc/seljiao")
    public Integer seljiao(Integer reid){
        //校验
        if (reid==null){
            //记录日志
            log.info("【查询患者是否有未缴费的项目】 患者id为必传项");
            return null;
        }
        //调用service查询患者的项目缴费状态
        Integer result = cashierService.findProjectPaymentStatusByReportId(reid);
        return result;
    }

    /**
     * 询患者是否有已缴费，但是未做的项目
     * @param reid 患者id
     * @return
     */
    @PostMapping("/caocc/selwei")
    public Integer selwei(Integer reid){
        //校验
        if (reid==null){
            //记录日志
            log.info("【患者是否有已缴费，但是未做的项目】 患者id为必传项");
            return null;
        }
        //调用service查询患者是否有已缴费，但是未做的项目
        Integer result = cashierService.findPaymentAndNoResultByReportId(reid);
        return result;
    }

    /**
     * 查询患者病因
     * @param reid
     * @return
     */
    @PostMapping("/caocc/selbing")
    public R selbing(Integer reid){
        //校验
        if (reid==null){
            //记录日志
            log.info("【查询患者病因】 患者id为必传项");
            return null;
        }
        //调用service查询患者病因
        String result = reportService.findPathogenyByReportId(reid);

        return R.ok(result);
    }

    /**
     * 转住院
     * @param id 患者id
     * @param zhuan 病因
     * @return
     */
    @PostMapping("/zhuanyuan")
    public R zhuanyuan(Integer id, String zhuan){
        //校验
        if (id==null){
            //记录日志
            log.info("【转住院】 患者id为必传项");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"患者id为必传项");
        }
        if (StringUtils.isEmpty(zhuan)){
            //记录日志
            log.info("【转住院】 病因为必传项");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"病因为必传项");
        }

        //封装数据
        Report report = new Report();
        report.setReportId(id);
        report.setZhuan(zhuan);
        report.setState(4);
        //调用service修改state和zhuan
        reportService.updateReport(report);
        return R.ok("转住院成功");

    }

    //====================================折叠尾部=====================================================

    //处方划价
    //===================================折叠头部============================================

    /**
     * 查询当天患者信息
     * @param name 患者信息
     * @param page
     * @param limit
     * @return
     */
    @GetMapping("/caotake/tselpreson")
    public R tselpreson(String name,
                        @RequestParam(defaultValue = "1") Integer page ,
                        @RequestParam(defaultValue = "10") Integer limit){
        //调用service查询当天患者信息
        PageInfo<Report> pageInfo = reportService.findTheDayPersonByPage(name,page,limit);
        //封装数据
        long count = pageInfo.getTotal();
        List<Report> reportList = pageInfo.getList();
        List<ReportVO> data = new ArrayList<>();
        for (Report report : reportList) {
            ReportVO reportVO = new ReportVO();
            BeanUtils.copyProperties(report, reportVO);
            data.add(reportVO);
        }
        return R.ok(data, count);
    }

    /**
     * 展示药品信息
     * @param drugname 药品名称
     * @param page
     * @param limit
     * @return
     */
    @GetMapping("/caocc/seldrug")
    public R seldrug(String drugname,
                     @RequestParam(defaultValue = "1") Integer page ,
                     @RequestParam(defaultValue = "10") Integer limit){
        //调用service查询药品信息
        PageInfo<Pharmacy> pageInfo = pharmacyService.findByPharmacyByDrugNameAndPage(drugname,page,limit);
        long count = pageInfo.getTotal();
        List<Pharmacy> pharmacyList = pageInfo.getList();
        //封装
        List<PharmacyVO> data = new ArrayList<>();
        for (Pharmacy pharmacy : pharmacyList) {
            PharmacyVO pharmacyVO = new PharmacyVO();
            BeanUtils.copyProperties(pharmacy, pharmacyVO);
            data.add(pharmacyVO);
        }
        return R.ok(data, count);
    }

    /**
     * 展示患者的药品出纳信息
     * @param perid 当前患者id
     * @param page
     * @param limit
     * @return
     */
    @GetMapping("/caocc/selAll")
    public R selAll(Integer perid,
                    @RequestParam(defaultValue = "1") Integer page ,
                    @RequestParam(defaultValue = "10") Integer limit){
        //校验
        if (perid==null){
            //记录日志
            log.info("【展示患者的药品出纳信息】 当前患者id不可为空");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"当前患者id不可为空");
        }

        //调用service根据患者id查询该患者的药品出纳信息
        PageInfo<Cashier> pageInfo = cashierService.findCashierByReportIdAndPage(perid,page,limit);
        long count = pageInfo.getTotal();
        List<Cashier> cashierList = pageInfo.getList();

        //封装
        List<CashierDrugVO> data = new ArrayList<>();
        for (Cashier cashier : cashierList) {
            CashierDrugVO cashierDrugVO = new CashierDrugVO();
            BeanUtils.copyProperties(cashier, cashierDrugVO);
            data.add(cashierDrugVO);
        }
        return R.ok(data, count);
    }

    /**
     * 查询患者是否开过当前处方药
     * @param reid 患者id
     * @param mename 药品名称
     * @return
     */
    @PostMapping("/caocc/selchu")
    public Integer selchu(Integer reid , String mename){
        //调用service根据患者id和药品名称，查询cashier出纳表中是否有未缴费的当前药品，没有，返回0
        Integer result = cashierService.checkPaymentStatusByReportIdAndDrugName(reid,mename);
        return result;
    }

    /**
     * 修改患者病因
     * @param reid 患者id
     * @param bing 病因
     * @return
     */
    @PostMapping("/caocc/addbing")
    public R addbing(Integer reid , String bing){
        //校验
        if (reid==null){
            //记录日志
            log.info("【修改患者病因】 患者id为必传项");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"患者id为必传项");
        }
        if (StringUtils.isEmpty(bing)){
            //记录日志
            log.info("【修改患者病因】 病因为必传项");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"病因为必传项");
        }

        //封装
        Report report = new Report();
        report.setReportId(reid);
        report.setZhuan(bing);
        //调用service修改病因
        reportService.updateReport(report);
        return R.ok("添加病因成功");
    }

    /**
     * 给患者添加/修改处方信息
     * @param registerId 患者id
     * @param name 药品名称
     * @param num 药品数量
     * @return
     */
    @PostMapping("/caocc/addchu")
    public R addchu(Integer registerId , String name , Integer num){
        //校验
        if (registerId==null){
            //记录日志
            log.info("【给患者添加/修改处方信息】 患者id为必传项");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"患者id为必传项");
        }
        if (StringUtils.isEmpty(name)){
            //记录日志
            log.info("【给患者添加/修改处方信息】 药品名称为必传项");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"药品名称为必传项");
        }
        if (num==null){
            //记录日志
            log.info("【给患者添加/修改处方信息】 药品数量为必传项");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"药品数量为必传项");
        }

        //调用service,修改处方信息
        pharmacyService.updatePrescription(registerId,name,num);
        return R.ok("添加患者药品出纳信息成功");
    }


    /**
     * 删除处方信息
     * @param id cashier表主键id
     * @return
     */
    @PostMapping("/caocc/del")
    public R del(Integer id){
        //校验
        if (id==null){
            //记录日志
            log.info("【删除处方信息】 处方信息id为必传项");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"处方信息id为必传项");
        }
        //调用service根据处方信息id查询当前药品处方信息
        Cashier cashier = cashierService.findById(id);
        //获取缴费状态
        Integer mstate = cashier.getMstate();
        if (mstate!=0){
            log.info("【删除处方信息】 该处方信息已缴费，无法删除");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"该药品已缴费，无法删除");
        }
        //调用service删除处方信息（注意添加库存）
        cashierService.deleteById(id);
        return R.ok("删除药品成功!");
    }
    //===================================折叠尾部============================================

    //项目划价
    /**
     * 查询当天患者信息
     * @param name 患者信息
     * @param page
     * @param limit
     * @return
     */
    @GetMapping("/caocc/selpreson")
    public R selpreson(String name,
                        @RequestParam(defaultValue = "1") Integer page ,
                        @RequestParam(defaultValue = "10") Integer limit){
        //调用service查询当天患者信息
        PageInfo<Report> pageInfo = reportService.findTheDayPersonByPage(name,page,limit);
        //封装数据
        long count = pageInfo.getTotal();
        List<Report> reportList = pageInfo.getList();
        List<ReportVO> data = new ArrayList<>();
        for (Report report : reportList) {
            ReportVO reportVO = new ReportVO();
            BeanUtils.copyProperties(report, reportVO);
            data.add(reportVO);
        }
        return R.ok(data, count);
    }

    /**
     * 展示项目信息
     * @param projectName 项目名称
     * @param page
     * @param limit
     * @return
     */
    @GetMapping("/caoout/selout")
    public R selout(String projectName,
                     @RequestParam(defaultValue = "1") Integer page ,
                     @RequestParam(defaultValue = "10") Integer limit){
        //调用service查询项目信息
        PageInfo<OutPatientType> pageInfo = outPatientTypeService.findByProjectNameAndPage(projectName,page,limit);
        long count = pageInfo.getTotal();
        List<OutPatientType> outPatientTypeList = pageInfo.getList();
        //封装
        List<OutPatientTypeVO> data = new ArrayList<>();
        for (OutPatientType outPatientType : outPatientTypeList) {
            OutPatientTypeVO outPatientTypeVO = new OutPatientTypeVO();
            BeanUtils.copyProperties(outPatientType, outPatientTypeVO);
            data.add(outPatientTypeVO);
        }
        return R.ok(data, count);
    }

    /**
     * 展示患者的项目出纳信息
     * @param perid 当前患者id
     * @param page
     * @param limit
     * @return
     */
    @GetMapping("/caocc/selximu")
    public R selximu(Integer perid,
                    @RequestParam(defaultValue = "1") Integer page ,
                    @RequestParam(defaultValue = "10") Integer limit){
        //校验
        if (perid==null){
            //记录日志
            log.info("【展示患者的项目出纳信息】 当前患者id不可为空");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"当前患者id不可为空");
        }

        //调用service根据患者id查询该患者的项目出纳信息
        PageInfo<Cashier> pageInfo = cashierService.findByReportIdAndPage(perid,page,limit);
        long count = pageInfo.getTotal();
        List<Cashier> cashierList = pageInfo.getList();

        //封装
        List<CashierVO> data = new ArrayList<>();
        for (Cashier cashier : cashierList) {
            CashierVO cashierVO = new CashierVO();
            BeanUtils.copyProperties(cashier, cashierVO);
            data.add(cashierVO);
        }
        return R.ok(data, count);
    }

    /**
     * 给患者添加处方信息
     * @param reportId
     * @param durgname
     * @return
     */
    @PostMapping("/caoout/addchuo")
    public R addchuo(Integer reportId , String durgname ){
        //校验
        if (reportId==null){
            //记录日志
            log.info("【给患者添加项目出纳信息】 患者id为必传项");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"患者id为必传项");
        }
        if (StringUtils.isEmpty(durgname)){
            //记录日志
            log.info("【给患者添加项目出纳信息】 项目名称为必传项");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"项目名称为必传项");
        }

        //调用service根据项目名称查询项目
        PageInfo<OutPatientType> pageInfo = outPatientTypeService.findByProjectNameAndPage(durgname, 1, 1);
        OutPatientType outPatientType = pageInfo.getList().get(0);
        //获取项目单价
        Double price = outPatientType.getPrice();
        //获取项目检查类型
        Integer ostate = outPatientType.getOstate();
        //封装
        Cashier cashier = new Cashier();
        cashier.setReportId(reportId);
        cashier.setDurgName(durgname);
        cashier.setDurgNum(1);
        cashier.setRepicePrice(price);
        cashier.setRepiceTotal(price);
        cashier.setState(1);
        cashier.setCtime(new Date());
        cashier.setOstate(ostate);
        cashier.setMstate(0);
        cashierService.addCashier(cashier);
        return R.ok("添加患者项目出纳信息成功！");
    }

    /**
     * 删除项目出纳信息
     * @param cashier cashier表主键id
     * @return
     */
    @PostMapping("/cao/delo")
    public R delo(Integer cashier){
        //校验
        if (cashier==null){
            //记录日志
            log.info("【删除项目出纳信息】 处方信息id为必传项");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"项目信息id为必传项");
        }
        //调用service根据处方信息id查询当前项目信息
        Cashier cashier1 = cashierService.findById(cashier);
        //获取缴费状态
        Integer mstate = cashier1.getMstate();
        if (mstate!=0){
            log.info("【删除处方信息】 该项目信息已缴费，无法删除");
            return R.error(HospitalExceptionEnum.INVALID_PARAMETER,"该项目已缴费，无法删除");
        }
        //调用service删除项目信息（注意添加库存）
        cashierService.deleteProjectById(cashier);
        return R.ok("删除项目成功!");
    }
}
